﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Aim2 {

    public enum Side {
        Player,
        Ennemy,
        Neutral,
        Harmless
    }

    class CollisionManager {
        public const float TimeToBecomeActive = 0.5f;

        public List<IObjectContainer> containers { get; set; }
        private List<Collision> collisions;

        private static CollisionManager instance;
        public static CollisionManager Instance {
            get {
                if (instance == null)
                    instance = new CollisionManager();
                return instance;
            }
        }

        private CollisionManager() {
            containers = new List<IObjectContainer>();
            collisions = new List<Collision>();
        }

        public void Register(IObjectContainer container) {
            this.containers.Add(container);
        }

        public void BuildCollisions() {
            collisions.Clear();
            List<AnimatedObject> playerSide = new List<AnimatedObject>();
            List<AnimatedObject> ennemySide = new List<AnimatedObject>();
            List<AnimatedObject> neutralSide = new List<AnimatedObject>();

            foreach (IObjectContainer container in containers) {
                playerSide.AddRange(container.Where(x => x.Side() == Side.Player && !x.Inactive));
                ennemySide.AddRange(container.Where(x => x.Side() == Side.Ennemy && !x.Inactive));
                neutralSide.AddRange(container.Where(x => x.Side() == Side.Neutral && !x.Inactive));
            }

            PlayerAgainstEnnemy(playerSide, ennemySide);
            PlayerAgainstNeutral(playerSide, neutralSide);
            EnnemyAgainstNeutral(ennemySide, neutralSide);

            foreach (IObjectContainer container in containers)
                container.RemovePending();
        }

        public void ApplyCollisions() {
            foreach (Collision c in collisions)
                c.Party.TakeDamage(c.Damage);
        }

        private bool valueInRange(int value, int min, int max) { 
            return (value >= min) && (value <= max); 
        }

        private bool IsThereCollision(AnimatedObject a, AnimatedObject b) {
            Rectangle A = a.HitBox;
            Rectangle B = b.HitBox;

            bool xOverlap = valueInRange(A.X, B.X, B.X + B.Width) ||
                    valueInRange(B.X, A.X, A.X + A.Width);

            bool yOverlap = valueInRange(A.Y, B.Y, B.Y + B.Height) ||
                            valueInRange(B.Y, A.Y, A.Y + B.Height);

            return xOverlap && yOverlap;
        }

        private void PlayerAgainstEnnemy(List<AnimatedObject> playerSide, List<AnimatedObject> ennemySide) {
            for (int p = 0; p < playerSide.Count; p++) {
                for (int e = 0; e < ennemySide.Count; e++) {
                    if(IsThereCollision(playerSide[p], ennemySide[e])) {
                        collisions.Add(new Collision(playerSide[p], ennemySide[e].CollisionDamage));
                        collisions.Add(new Collision(ennemySide[e], playerSide[p].CollisionDamage));
                    }
                }
            }
        }

        private void PlayerAgainstNeutral(List<AnimatedObject> playerSide, List<AnimatedObject> neutralSide) {
            for (int p = 0; p < playerSide.Count; p++) {
                for (int e = 0; e < neutralSide.Count; e++) {
                    if (IsThereCollision(playerSide[p], neutralSide[e])) {
                        collisions.Add(new Collision(playerSide[p], neutralSide[e].CollisionDamage));
                        collisions.Add(new Collision(neutralSide[e], playerSide[p].CollisionDamage));
                    }
                }
            }

        }

        private void EnnemyAgainstNeutral(List<AnimatedObject> ennemySide, List<AnimatedObject> neutralSide) {
            for (int p = 0; p < ennemySide.Count; p++) {
                for (int e = 0; e < neutralSide.Count; e++) {
                    if (IsThereCollision(ennemySide[p], ennemySide[e])) {
                        collisions.Add(new Collision(ennemySide[p], ennemySide[e].CollisionDamage));
                        collisions.Add(new Collision(ennemySide[e], ennemySide[p].CollisionDamage));
                    }
                }
            }

        }
    }
}
